/*************  技术支持与购买说明    **************
产品主页：http://tw51.haohaodada.com
淘宝搜索：天问51，可购买。目前基础版99元，带彩屏标准备版149元，旗舰版299
技术支持QQ群一：1138055784
******************************************/

#ifndef __DHT11_H
#define __DHT11_H

#include <STC8HX.h>
#include "delay.h" 

#ifndef DHT11_DQ
#define DHT11_DQ       	P4_6
#endif

#ifndef DHT11_DQ_MODE
#define DHT11_DQ_MODE	{P4M1&=~0x40;P4M0&=~0x40;}	//设置P46双向IO口
#endif

uint8 dht11_init();			  //DHT11初始化
uint8 dht11_read_data(uint8 *dat);//读数据
float dht11_read_temp();//读温度
uint8 dht11_read_humidity();//读湿度

//========================================================================
// 描述: 延时40us.
// 参数: none.
// 返回: none.
//========================================================================
static void delay40us()		//@24.000MHz
{
	unsigned char i, j;

	_nop_();
	i = 2;
	j = 60;
	do
	{
		while (--j);
	} while (--i);
}

//========================================================================
// 描述: DHT11复位.
// 参数: none.
// 返回: none.
//========================================================================
void dht11_rst()
{
    DHT11_DQ = 0;                  // 主机发送开始工作信号
    delay(20);                     //延时18ms以上
    DHT11_DQ = 1; 
    delay40us();
}

//========================================================================
// 描述: 等待DHT11的回应.
// 参数: none.
// 返回: 超时返回1，否则返回0.
//========================================================================
uint8 dht11_check() 	   
{   
	uint8 retry=0;
    while (DHT11_DQ&&retry<100)//DHT11会拉低40~80us
	{
		retry++;
		delay1us();	
	};	 
	if(retry>=100)return 1;
	else retry=0;
    while (!DHT11_DQ&&retry<100)//DHT11拉低后会再次拉高40~80us
	{
		retry++;
		delay1us();
	};
	if(retry>=100)return 1;	    
	return 0;
}

//========================================================================
// 描述: DHT11读一个位.
// 参数: none.
// 返回: 读到的位.
//========================================================================
uint8 dht11_read_bit() 			 
{
 	uint8 retry=0;
	while(DHT11_DQ&&retry<100)//等待变为低电平
	{
		retry++;
		delay1us();
	}
	retry=0;
	while(!DHT11_DQ&&retry<100)//等待变高电平
	{
		retry++;
		delay1us();
	}
	delay40us();//等待40us
	if(DHT11_DQ)return 1;
	else return 0;		   
}

//========================================================================
// 描述: DHT11读一个字节.
// 参数: none.
// 返回: 读到的字节.
//========================================================================
uint8 dht11_read_byte()    
{        
    uint8 i,dat;
    dat=0;
	for (i=0;i<8;i++) 
	{
   		dat<<=1; 
	    dat|=dht11_read_bit();
    }						    
    return dat;
}

//========================================================================
// 描述: DHT11读4字节数据.
// 参数: dat:读回的4字节数据数据指针.
// 返回: 成功返回0，失败返回1.
//========================================================================
uint8 dht11_read_data(uint8 *dat)      
{
 	uint8 buf[5];
	uint8 i;
	dht11_rst();
	
	if(dht11_check()==0)
	{
		for(i=0;i<5;i++)//读取40位数据
		{
			buf[i]=dht11_read_byte();
		}
		if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
		{
			*dat = buf[0];
			*(dat+1) = buf[1];
			*(dat+2) = buf[2];
			*(dat+3) = buf[3];
		}
	}else return 1;
	return 0;	
}

//========================================================================
// 描述: DHT11初始化.
// 参数: none.
// 返回: 识别到DHT11返回0，否则返回1.
//========================================================================
uint8 dht11_init()
{
    DHT11_DQ_MODE;
    DHT11_DQ = 1;    
    dht11_rst();
    return dht11_check();
}

//========================================================================
// 描述: DHT11读湿度.
// 参数: none.
// 返回: 湿度值
//========================================================================
uint8 dht11_read_humidity()
{
	uint8 value[4];
	if(dht11_read_data(value) != 0)	//读取失败
	{
		return 255;	
	}else{							//读取成功
		return value[0];		
	}
}

//========================================================================
// 描述: DHT11读温度.
// 参数: none.
// 返回: 温度值
//========================================================================
float dht11_read_temp()
{
	uint8 value[4];
	uint8 err;
	float f;
	if(dht11_read_data(value) != 0)	//读取失败
	{
		return 255;
	}
	f = value[2] & 0x7F;
    f *= 10;
    f += value[3];
    f /= 10;
    if (value[2] & 0x80)
        f *= -1;
	return f;
}

#endif		//dht11.h